﻿////////////////////////////////////////////////////////////////////////////////////////////
// File: FountainEffect.cs                                                                //
// Author: Mike Binnix                                                                    //
// Desc: Particle effect of a fountain the spews out particles.  Hanldes the creation of  //
//       particles with the correct attributes and adds them into the ParticleManager.    //
//       Can be used for things such as sparks shooting out from objects grinding.        //
////////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace SlothEngine.Physics.ParticleEffects
{
    public class FountainEffect
    {
        #region Attributes
        protected Vector2 position;
        protected Texture2D image;
        protected Vector2 minVelocity;
        protected Vector2 maxVelocity;
        protected TimeSpan maxAge;
        protected int maxParticles;
        protected List<EffectParticle> particleList;
        protected Random rand;
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the current position of the fountain.
        /// </summary>
        public Vector2 Position
        {
            get
            {
                return position;
            }
            set
            {
                position = value;
            }
        }
        /// <summary>
        /// Gets of sets the image used for particles.
        /// </summary>
        public Texture2D Image
        {
            get
            {
                return image;
            }
            set
            {
                image = value;
            }
        }
        /// <summary>
        /// Gets or sets the maximum age for particles.
        /// </summary>
        public TimeSpan MaxAge
        {
            get
            {
                return maxAge;
            }
            set
            {
                maxAge = value;
            }
        }
        /// <summary>
        /// Gets of sets the maximum number of particles that fountain to have active at once.
        /// </summary>
        public int MaxParticles
        {
            get
            {
                return maxParticles;
            }
            set
            {
                if (value < 0)
                    maxParticles = 0;
                else
                    maxParticles = value;
            }
        }
        /// <summary>
        /// Gets or sets the minimum x and y velocities for particles.
        /// </summary>
        public Vector2 MinVelocity
        {
            get
            {
                return minVelocity;
            }
            set
            {
                minVelocity = value;
            }
        }
        /// <summary>
        /// Gets or sets the maximum x and y velocity for particles.
        /// </summary>
        public Vector2 MaxVelocity
        {
            get
            {
                return maxVelocity;
            }
            set
            {
                maxVelocity = value;
            }
        }
        #endregion

        #region Constructors
        public FountainEffect()
        {
            position = Vector2.Zero;
            image = null;
            minVelocity = Vector2.Zero;
            maxVelocity = Vector2.Zero;
            maxAge = TimeSpan.MaxValue;
            maxParticles = 256;
            particleList = new List<EffectParticle>();
            rand = new Random();
        }
        public FountainEffect(Vector2 position, TimeSpan maxAge, int maxParticles)
        {
            this.position = position;
            image = null;
            minVelocity = Vector2.Zero;
            maxVelocity = Vector2.Zero;
            this.maxAge = maxAge;
            this.maxParticles = maxParticles;
            particleList = new List<EffectParticle>();
            rand = new Random();
        }
        public FountainEffect(Vector2 position, TimeSpan maxAge, int maxParticles, Texture2D image, Vector2 minVelocity, Vector2 maxVelocity)
        {
            this.position = position;
            this.maxAge = maxAge;
            this.maxParticles = maxParticles;
            this.image = image;
            this.minVelocity = minVelocity;
            this.maxVelocity = maxVelocity;
            particleList = new List<EffectParticle>();
            rand = new Random();
        }
        #endregion

        #region Methods
        /// <summary>
        /// Creates a new EffectParticle to add to the fountain.
        /// </summary>
        /// <returns>Returns an EffectParticle with filled out attributes.</returns>
        public virtual void CreateParticle()
        {
            EffectParticle particle = new EffectParticle();

            // Effect particle properties
            particle.Position = position;
            particle.Image = image;
            particle.MaxAge = maxAge;
            particle.Scale = 1.0f;
            particle.Rotation = 0.0f;
            particle.Alpha = 255.0f;
            particle.BeginFadeIn = TimeSpan.Zero;
            particle.BeginFadeOut = TimeSpan.Zero;
            particle.FadeInDuration = TimeSpan.Zero;
            particle.FadeOutDuration = new TimeSpan(0, 0, 3);

            // physics properties
            particle.Mass = 1.0f;
            particle.Damping = 0.90f;                       // Simple drag
            particle.Acceleration = new Vector2(0, 9.81f);  // Simple gravity
            particle.Velocity = new Vector2((float)rand.Next((int)minVelocity.X, (int)maxVelocity.X), (float)rand.Next((int)minVelocity.Y, (int)maxVelocity.Y));

            particleList.Add(particle);
        }
        /// <summary>
        /// Updates particles created by the fountain.
        /// </summary>
        /// <param name="gameTime">Time since last update.</param>
        public virtual void Update(GameTime gameTime)
        {
            // Remove old particles
            for (int i = 0; i < particleList.Count; i++)
                if (particleList[i].Destroy)
                    particleList.RemoveAt(i);

            // Update all other particles
            foreach (EffectParticle particle in particleList)
                particle.Update(gameTime);

            // Create new particle
            if (particleList.Count < maxParticles)
            {
                CreateParticle();
            }
        }
        /// <summary>
        /// Draw particles to screen.
        /// </summary>
        /// <param name="spriteBatch">SpriteBatch used for drawing.</param>
        public virtual void Draw(SpriteBatch spriteBatch)
        {
            foreach (EffectParticle particle in particleList)
                particle.Draw(spriteBatch);
        }
        #endregion
    }
}
